#include "display_dev.h"

/*
/*显示屏 display_dev 文件
/*实现 Display_dev 结构体
/*使用方法：
/*			将设备加入设备链表
/*			驱动通过名字绑定该设备
/*			同时将设备反向绑定驱动，实现双方绑定
/*			驱动调用设备初始化，初始化设备
/*			既可合理在设备上描点
/*不合理的地方，链表初始化不知道如何放置
*/

static int display_screen_fd;



Display_dev current_screen_dev = {
	.name = "screen_dev" ,
	.bind_dir = screen_bind_dir ,
	.init_dev = screen_init ,
	.get_args = screen_get_args ,
	.show_pix = screen_show_pix ,
	.next = NULL ,
};

/*
/*绑定驱动
/*根据传入的名字进行绑定
*/

static int screen_bind_dir(char* name) {  //这里有点问题不应该放这
	current_screen_dev.dir_name = name;
	return 0;
}

/*
/*返回该驱动的设备参数
/*保存在驱动结构体中
*/

static pDisplay_dev_arg_t screen_get_args() {
	return current_screen_dev.screen_args;
}


/*
/*初始化该设备
/*打开对应的设备文件
/*解析设备参数
/*保存设备参数
*/

static int screen_init() {
	current_screen_dev.screen_args = (pDisplay_dev_arg_t)malloc(sizeof(Display_dev_arg_t));
	display_screen_fd = open("/dev/fb0",O_RDWR);
	struct fb_var_screeninfo vinfo;
	if(display_screen_fd < 0) {
		printf("open /dev/fb0 err \n");
		return -1;
	}
	if(ioctl(display_screen_fd, FBIOGET_VSCREENINFO, &vinfo)) {
		printf("get vinfo err \n");
		return -1;
	}
	current_screen_dev.screen_args->bpp = vinfo.bits_per_pixel/8;
	current_screen_dev.screen_args->xres = vinfo.xres * current_screen_dev.screen_args->bpp;
	current_screen_dev.screen_args->yres = vinfo.yres * current_screen_dev.screen_args->bpp;
	current_screen_dev.screen_args->size = current_screen_dev.screen_args->xres *  current_screen_dev.screen_args->yres / current_screen_dev.screen_args->bpp;
	current_screen_dev.screen_args->base_addr = (unsigned char*)mmap(NULL,current_screen_dev.screen_args->size,PROT_READ | PROT_WRITE,MAP_SHARED,display_screen_fd,0);
	if(current_screen_dev.screen_args->base_addr == (unsigned char *) -1) {
		printf("the mmap err \n");
		return -1;
	}
	return 0;
	
}

/*
/*使用该设备
/*在设备中画出一个对应颜色的点
/*传入参数，设置点的坐标，以及显示的4字节颜色值
*/

static void screen_show_pix(int x,int y,unsigned int color) {
	unsigned char *pen_8 = current_screen_dev.screen_args->base_addr + y*current_screen_dev.screen_args->xres+ x*current_screen_dev.screen_args->bpp;
	unsigned short * pen_16 = (unsigned short *)pen_8;
	unsigned int * pen_32 = (unsigned int *)pen_8;
	unsigned char red,green,blue;
	switch(current_screen_dev.screen_args->bpp*8) {
		case 8:
	        *pen_8 = color;
	        break;
		case 16: //565模式
            red = (color>>16) & 0xff;
			
            green = (color>>8) & 0xff;
			blue = color & 0xff;
			color = ((red >>3 ) << 11) | ((green >> 2) << 5) | (blue >>3);
			*pen_16 = color;
			//printf("this %d \n",current_screen_dev.screen_args->base_addr);
			break;
		case 32:
			*pen_32 = color;
			break;
		default:
			break;
	}

}


int add_to_list(pDisplay_dev pcurrent_dev) {
	if(head_dev == NULL){
		head_dev = (pDisplay_dev)malloc(sizeof(Display_dev));
	}
	pDisplay_dev buf_dev = head_dev;
	while(buf_dev->next != NULL) {
		buf_dev = buf_dev->next;
	}
	buf_dev->next = pcurrent_dev;
	return 0;
}






